#ifndef RSACRYPTO_H
#define RSACRYPTO_H

#include <QObject>
#include <QByteArray>
#include <QMap>
#include <QCryptographicHash>
#include <openssl/evp.h>

class RsaCrypto : public QObject
{
    Q_OBJECT
public:
    // 密钥的位数长度
    enum KeyLength {
        BITS_1K = 1024,
        BITS_2K = 2048,
        BITS_3K = 3072,
        BITS_4K = 4096,
    };

    // 密钥类型: 公钥 or 私钥
    enum KeyType { PublicKey, PrivateKey };

    // 定义指向哈希函数的函数指针
    using hashFunc = const EVP_MD* (*)(void);

    explicit RsaCrypto(QObject *parent = nullptr);
    // 构造对象并加载密钥文件(密钥以文件的形式存储在磁盘中)中的数据到内存中
    explicit RsaCrypto(QByteArray fileName, KeyType type, QObject* parent = nullptr);
    ~RsaCrypto();

    // 将密钥字符串解析为密钥类型
    void parseStringToKey(QByteArray data, KeyType type);
    // 生成密钥对
    void generateRsaKey(KeyLength bits, QByteArray pub = "public.pem", QByteArray pri = "private.pem");
    // 通过公钥进行加密
    QByteArray pubKeyEncrypt(QByteArray data);
    // 通过私钥进行解密
    QByteArray privateKeyDecrypt(QByteArray data);
    // 数字签名
    QByteArray sign(QByteArray data, QCryptographicHash::Algorithm hash = QCryptographicHash::Sha256);
    // 签名校验
    bool verify(QByteArray sign, QByteArray data, QCryptographicHash::Algorithm hash = QCryptographicHash::Sha256);

signals:

private:
    EVP_PKEY* m_pubkey = NULL;
    EVP_PKEY* m_prikey = NULL;
    const QMap<QCryptographicHash::Algorithm, hashFunc> m_hashMethods = {
        {QCryptographicHash::Md5, EVP_md5},
        {QCryptographicHash::Sha1, EVP_sha1},
        {QCryptographicHash::Sha224, EVP_sha224},
        {QCryptographicHash::Sha256, EVP_sha256},
        {QCryptographicHash::Sha384, EVP_sha384},
        {QCryptographicHash::Sha512, EVP_sha512},
        {QCryptographicHash::Sha3_224, EVP_sha3_224},
        {QCryptographicHash::Sha3_256, EVP_sha3_256},
        {QCryptographicHash::Sha3_384, EVP_sha3_384},
        {QCryptographicHash::Sha3_512, EVP_sha3_512},
    };
};

#endif // RSACRYPTO_H
